package game.display;

import java.awt.Image;
import java.util.ArrayList;

/**
    The Animation class manages a series of images (frames) and
    the amount of time to display each frame.
*/
public class Animation {

    private ArrayList<AnimFrame> frames;
    private int currFrameIndex;
    private long animTime;
    private long totalDuration;
    private boolean repeats;
    private boolean isDone;
    /**
        Creates a new, empty Animation.
    */
    public Animation() {
        frames = new ArrayList<AnimFrame>();
        totalDuration = 0;
        repeats = true;
        isDone = false;
        start();
    }
    public boolean repeats() {
       return repeats;
    }
    public Animation setRepeats(boolean r) {
       repeats = r;
       return this;
    }
    public boolean isDone() {
       return isDone;
    }

    /**
        Adds an image to the animation with the specified
        duration (time to display the image).
    */
    public synchronized Animation addFrame(Image image,
        long duration)
    {
        totalDuration += duration;
        frames.add(new AnimFrame(image, totalDuration));
        return this;
    }


    /**
        Starts this animation over from the beginning.
    */
    public synchronized void start() {
        animTime = 0;
        currFrameIndex = 0;
    }


    /**
        Updates this animation's current image (frame), if
        necessary.
    */
    public synchronized void update(long elapsedTime) {
    	if (frames.size() > 1) {
            animTime += elapsedTime;
            if (animTime >= totalDuration) {
               animTime = animTime % totalDuration;
               currFrameIndex = 0;
               if(!repeats) {
                  isDone = true;
                  return;
               }
            }

            while (animTime > getFrame(currFrameIndex).endTime) {
                currFrameIndex = (currFrameIndex + 1)% frames.size();
            }
        }
    }


    /**
        Gets this Animation's current image. Returns null if this
        animation has no images.
    */
    public synchronized Image getImage() {
        if (frames.size() == 0) {
            return null;
        }
        else {
            return getFrame(currFrameIndex).image;
        }
    }


    private AnimFrame getFrame(int i) {
        return (AnimFrame)frames.get(i);
    }
    public Animation clone() {
       Animation a = new Animation();
       long lastFrameTime = 0;
       for(AnimFrame af: frames) {
          a.addFrame(af.image, af.endTime-lastFrameTime);
          lastFrameTime = af.endTime;
       }
       return a.setRepeats(repeats);
    }

    private class AnimFrame {

        Image image;
        long endTime;

        public AnimFrame(Image image, long endTime) {
            this.image = image;
            this.endTime = endTime;
        }
    }
}
